package com.skcc.cop.mrtaxi4driver.biz;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.location.Location;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.skcc.cop.mrtaxi4driver.BaseActivity;
import com.skcc.cop.mrtaxi4driver.R;
import com.skcc.cop.mrtaxi4driver.util.Dialogs;
import com.skcc.cop.mrtaxi4driver.util.Dialogs.DialogListener;
import com.skcc.cop.mrtaxi4driver.util.GCMUtils;
import com.skcc.cop.mrtaxi4driver.util.LocationUtils;
import com.skcc.cop.mrtaxi4driver.util.Variables;
import com.skcc.cop.mrtaxi4driver.view.TitleBar;
import com.skcc.cop.mrtaxi4driver.view.TitleBar.OnTitleBarEventListener;


// TODO: 
//  1. 음성인식 대기 시간을 늘릴 수 있나? 
//  taemin :  가능
public class HomeActivity extends BaseActivity implements
		OnTitleBarEventListener, OnInitListener, OnUtteranceCompletedListener,
		LocationListener,
		GooglePlayServicesClient.ConnectionCallbacks,
		GooglePlayServicesClient.OnConnectionFailedListener {

	// ===========================================================
	// Constants
	// ===========================================================
	private static final String TAG = HomeActivity.class.getSimpleName();
	
	// ACTION_RECOGNIZE_SPEECH
	private static final int REQUEST_CODE = 1234;
	
	
	// ===========================================================
    // Fields
    // ===========================================================
	public static boolean isForeground = false;
	
	// A request to connect to Location Services
    private LocationRequest mLocationRequest;
    // Stores the current instantiation of the location client in this object
    private LocationClient mLocationClient;
    
	private TitleBar mTitleBarView;

	private String callId;
	private String message;
	private AlertDialog dialog;
	private TextToSpeech textToSpeech;
	private HashMap<String, String> params = new HashMap<String, String>();

	
	// ===========================================================
    // Constructors
    // ===========================================================
	
	
	// ===========================================================
    // Methods for/from SuperClass/Interfaces
    // ===========================================================
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_home);
		
		// sleep 모드 방지
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		
		textToSpeech = new TextToSpeech(this, this);

		mTitleBarView = (TitleBar) this.findViewById(R.id.titlebar_view);
		mTitleBarView.setEventListener(this);
		mTitleBarView.showBack();
		mTitleBarView.setTitle(R.string.title);

		// Create a new global location parameters object (location client)
        mLocationRequest = LocationRequest.create();
        // Set the update interval
        mLocationRequest.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
        // Use high accuracy
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        // Set the interval ceiling to one minute
        mLocationRequest.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
        
        // Create a new location client, using the enclosing class to handle callbacks.
        mLocationClient = new LocationClient(this, this, this);
		
        callId = getIntent().getStringExtra(Variables.CALL_ID);
		message = getIntent().getStringExtra(Variables.CALL_MESSAGE);
		Log.i(TAG, ""+message);
        //message = "에스케이씨앤씨";
	}

	@Override
	protected void onNewIntent(Intent intent) {
		super.onNewIntent(intent);

		message = intent.getExtras().getString(Variables.CALL_MESSAGE);
	}

    // Called when the Activity becomes visible.
    @Override
    protected void onStart() {
        super.onStart();
        
        // Connect the client.
        mLocationClient.connect();
    }
	
	@Override
	protected void onResume() {
		super.onResume();

		Log.d(TAG, " in onResume >>>>>");

		isForeground = true;

		registerReceiver(mHandleMessageReceiver, new IntentFilter(
				GCMUtils.NOTIFY_CALL_MESSAGE_ACTION));
	}
	
	@Override
	protected void onPause() {
		super.onPause();

		Log.d(TAG, " in onPause >>>>>");

		isForeground = false;

		unregisterReceiver(mHandleMessageReceiver);
	}
	
    // Called when the Activity is no longer visible.
    @Override
    protected void onStop() {
    	// If the client is connected
        if (mLocationClient.isConnected()) {
        	mLocationClient.removeLocationUpdates(this);
        }
    	
        // Disconnecting the client invalidates it.
        mLocationClient.disconnect();
        
        super.onStop();
    }

	@Override
	protected void onDestroy() {
		// application.resetResource();

		Log.d(TAG, " in onDestroy >>>>>");
		
		textToSpeech.shutdown();
		
		super.onDestroy();
	}

	@Override
	public void onBackPressed() {

		Dialogs.showDialogYesNo(HomeActivity.this, getString(R.string.confirm_finish), new DialogListener() {
			
			@Override
			public void onClickedOk() {
				finish();
			}

			@Override
			public void onClickedCancel() {
				Dialogs.dismiss();
			}
		});

	}

	@Override
	public void onBackClicked() {
		Intent intent = new Intent(this, HistoryActivity.class);
		startActivity(intent);
	}
	
	@Override
	public void onUtteranceCompleted(String utteranceId) {
		if (dialog != null) {
			// 음성인식 모듈 실행
			Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
			intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
					RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
			
//			intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 10000); 
//			intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 200000);
//			intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 200000);
			
			intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Voice Recognition...");
			
			startActivityForResult(intent, REQUEST_CODE);
		}
	}

	@Override
	public void onInit(int status) {
		if (status == TextToSpeech.SUCCESS) {
			
			textToSpeech.setOnUtteranceCompletedListener(this);
			
			int result = textToSpeech.setLanguage(Locale.KOREA);
			if (result == TextToSpeech.LANG_MISSING_DATA
					|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
				Log.e("error", "This Language is not supported");
			} else {
				
				 if (message != null && !"".equals(message)) {
					params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, message);
					showDialog(0);
				 }
			}
		} else {
			Log.e("error", "Initilization Failed!");
		}
	}
	
	@Override
	protected Dialog onCreateDialog(int id) {
		
		switch (id)
		{
			case 0:
			{
				dialog = new AlertDialog.Builder(this)
						.setIcon(R.drawable.alert_icon_notice)
						.setTitle("Call Request")
						.setMessage(message)
						.setCancelable(true)
						.show();
				
				return dialog;
			}
		}
		
		return super.onCreateDialog(id);
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		System.out.println("===============  HomeActivity.onPrepareDialog  ");

		switch (id) {
			case 0: {
				
				textToSpeech.speak(message, TextToSpeech.QUEUE_FLUSH, params);
				
				((AlertDialog) dialog).setMessage(message);
				break;
			}
		}

		super.onPrepareDialog(id, dialog);
	}
	
	@Override
	public void onConnectionFailed(ConnectionResult connectionResult) {
		/*
         * Google Play services can resolve some errors it detects.
         * If the error has a resolution, try sending an Intent to
         * start a Google Play services activity that can resolve
         * error.
         */
        if (connectionResult.hasResolution()) {
            try {

                // Start an Activity that tries to resolve the error
                connectionResult.startResolutionForResult(
                        this,
                        LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);

                /*
                * Thrown if Google Play services canceled the original
                * PendingIntent
                */

            } catch (IntentSender.SendIntentException e) {

                // Log the error
                e.printStackTrace();
            }
        } else {

            // If no resolution is available, display a dialog to the user with the error.
            showErrorDialog(connectionResult.getErrorCode());
        }
	}

	/*
     * Called by Location Services when the request to connect the
     * client finishes successfully. At this point, you can
     * request the current location or start periodic updates
     */
	@Override
	public void onConnected(Bundle arg0) {
		if (servicesConnected()) {
			mLocationClient.requestLocationUpdates(mLocationRequest, this);
		}
	}

	@Override
	public void onDisconnected() {
		// Display the connection status
        Toast.makeText(this, "Disconnected. Please re-connect.",
                Toast.LENGTH_SHORT).show();
	}
	
	@Override
	public void onLocationChanged(Location location) {
		registerDriverPos(location.getLatitude(), location.getLongitude());
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		// Choose what to do based on the request code
        switch (requestCode) {
        	// If the request code matches the code sent in onConnectionFailed
        	case LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST :

	            switch (resultCode) {
	                // If Google Play services resolved the problem
	                case Activity.RESULT_OK:
	                    // Log the result
	                    Log.d(LocationUtils.APPTAG, getString(R.string.resolved));
	                break;

	                // If any other result was returned by Google Play services
	                default:
	                    // Log the result
	                    Log.d(LocationUtils.APPTAG, getString(R.string.no_resolution));
	                break;
	            }
	            
	        // ACTION_RECOGNIZE_SPEECH
        	case REQUEST_CODE :    
        		switch (resultCode) {
	                case Activity.RESULT_OK:

            		boolean flag = false;
            		ArrayList<String> matches = new ArrayList<String> ();
            		matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
        			
            		String[] yes = getResources().getStringArray(R.array.voice_recognition_validation_yes);
        			
        			int size = yes.length;
        			for (String match : matches) {
        				for (int i=0; i<size; i++) {
        					// TODO: containsAll 사용??
        					if (match.trim().equalsIgnoreCase(yes[i])) {
        						flag = true;
        						break;
        					}
        				}
        			}
        			
        			sendResponse(flag);
        			
        			break;
        		}
	            
	        // If any other request code was received
	        default:
	           // Report that this Activity received an unknown requestCode
	           Log.d(LocationUtils.APPTAG,
	                   getString(R.string.unknown_activity_request_code, requestCode));
	
	           break;
        }
	}
	
	
	// ===========================================================
    // Methods
    // ===========================================================
	private void sendResponse(boolean flag) {
		if (dialog != null) {
			dialog.dismiss();
		}
		
		sendDriverResponse(flag);
	}
	
	private void sendDriverResponse(boolean flag) {
		Log.i(TAG, ">>>>>>>>> 11111111111111111111111111111 " + flag);
		
		gateway.acceptCustomerReq(callId, flag ? Variables.BOOLEAN_VALUE_Y:Variables.BOOLEAN_VALUE_N);
		if (flag) {
			Toast.makeText(this, getString(R.string.okay_call_request), Toast.LENGTH_LONG).show();
		} else {
			Toast.makeText(this, getString(R.string.refuse_call_request), Toast.LENGTH_LONG).show();
		}

	}
	
	 /**
     * Verify that Google Play services is available before making a request.
     *
     * @return true if Google Play services is available, otherwise false
     */
    private boolean servicesConnected() {

        // Check that Google Play services is available
        int resultCode =
                GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

        // If Google Play services is available
        if (ConnectionResult.SUCCESS == resultCode) {
            // In debug mode, log the status
            Log.d(LocationUtils.APPTAG, getString(R.string.play_services_available));

            // Continue
            return true;
        // Google Play services was not available for some reason
        } else {
            // Display an error dialog
            Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0);
            if (dialog != null) {
                ErrorDialogFragment errorFragment = new ErrorDialogFragment();
                errorFragment.setDialog(dialog);
                errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
            }
            return false;
        }
    }
	
	/**
     * Show a dialog returned by Google Play services for the
     * connection error code
     *
     * @param errorCode An error code returned from onConnectionFailed
     */
    private void showErrorDialog(int errorCode) {

        // Get the error dialog from Google Play services
        Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
            errorCode,
            this,
            LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);

        // If Google Play services can provide an error dialog
        if (errorDialog != null) {

            // Create a new DialogFragment in which to show the error dialog
            ErrorDialogFragment errorFragment = new ErrorDialogFragment();

            // Set the dialog in the DialogFragment
            errorFragment.setDialog(errorDialog);

            // Show the error dialog in the DialogFragment
            errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
        }
    }
	
	// 택시 기사의 위치를 서버로 전송하는 메소드
	private void registerDriverPos(double latitude, double longitude) {
		gateway.registerDriverPos(latitude, longitude);		// 피드백을 받을 필요 없음.
	}
	
	 
    // ===========================================================
    // Inner and Anonymous Classes
    // ===========================================================
	private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			callId = intent.getExtras().getString(Variables.CALL_ID);
			message = intent.getExtras().getString(Variables.CALL_MESSAGE);
			Log.i(TAG, message);

			showDialog(0);
		}
	};
	
	
	private DialogListener dialogListener = new DialogListener() {

		@Override
		public void onClickedOk() {
			Dialogs.dismiss();
			
			finish();
		}

		@Override
		public void onClickedCancel() {
			// TODO Auto-generated method stub
		}
	};

	/**
     * Define a DialogFragment to display the error dialog generated in
     * showErrorDialog.
     */
    public static class ErrorDialogFragment extends DialogFragment {

        // Global field to contain the error dialog
        private Dialog mDialog;

        /**
         * Default constructor. Sets the dialog field to null
         */
        public ErrorDialogFragment() {
            super();
            mDialog = null;
        }

        /**
         * Set the dialog to display
         *
         * @param dialog An error dialog
         */
        public void setDialog(Dialog dialog) {
            mDialog = dialog;
        }

        /*
         * This method must return a Dialog to the DialogFragment.
         */
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return mDialog;
        }
    }

}
